package com.oanda.blackberry.view;

import com.oanda.blackberry.OandaBlackBerryApplication;
import com.oanda.blackberry.restapi.Order;
import com.oanda.blackberry.restapi.OrderListResponse;
import com.oanda.blackberry.restapi.OrderPollResponse;
import com.oanda.blackberry.restapi.Rate;
import com.oanda.blackberry.ui.OandaMainScreen;
import com.oanda.blackberry.util.AbstractController;
import com.oanda.blackberry.util.AbstractViewPanel;
import com.oanda.blackberry.util.DefaultController;
import com.oanda.blackberry.util.Model;
import com.oanda.blackberry.util.PropertyChangeEvent;
import com.oanda.blackberry.util.log.Logger;
import java.util.Timer;
import java.util.TimerTask;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.Screen;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.BackgroundFactory;

public class OrdersView implements AbstractViewPanel {
	DefaultController controller;
	VerticalFieldManager listManager = new VerticalFieldManager();

	HorizontalFieldManager hStatus = new HorizontalFieldManager();
	LabelField statusLabel = new LabelField();
	OrdersListField list;
	Timer updateTimer = new Timer();

	TimerTask updateTask = new TimerTask() {
		public synchronized void run() {
			if (OandaBlackBerryApplication.isInForeground) {
				OrdersView.this.orderPoll();
			} else {
				try {
					wait();
				} catch (InterruptedException e) {
				}
			}
		}
	};

	Timer quoteTimer = new Timer();

	TimerTask quoteTask = new TimerTask() {
		public synchronized void run() {
			if (OandaBlackBerryApplication.isInForeground) {
				OrdersView.this.quoteUpdates();
			} else {
				try {
					wait();
				} catch (InterruptedException e) {
				}
			}
		}
	};

	private long UPDATE_TIME = 10000L;

	private long UPDATE_TIME_QUOTE = 3000L;
	OandaMainScreen screen;
	MenuItem newOrder = new MenuItem("New Order", 10, 1000) {
		public void run() {
			OrdersView.this.controller.propertyChange(new PropertyChangeEvent(
					this, "newLimitOrderOpenBuy", null, null));
		}
	};

	MenuItem viewDetails = new MenuItem("View Details", 10, 1001) {
		public void run() {
			if (OrdersView.this.list != null) {
				OrderListResponse details = OrdersView.this.list
						.getOrderListSelected();
				if (details == null) {
					DefaultController
							.inform("Please wait for retrieving order details!");
					return;
				}
				OrdersView.this.controller.viewOrderDetails(details);
			} else {
				Logger.log("odv view details - null");
			}
		}
	};

	MenuItem cancelOrder = new MenuItem("Cancel Order", 10, 1002) {
		public void run() {
			if (4 == Dialog.ask(3,
					"Are you sure you want to cancel this order?"))
				if (OrdersView.this.list != null)
					OrdersView.this.controller.cancelOrder(OrdersView.this.list
							.getOrderListSelected());
				else
					Logger.log("odv view cancel - null");
		}
	};

	MenuItem back = new MenuItem("Back", 10, 1003) {
		public void run() {
			OrdersView.this.popScreen();
		}
	};

	public void notifyTimerTask() {
		if (this.updateTask != null) {
			synchronized (this.updateTask) {
				this.updateTask.notifyAll();
			}
		}
		if (this.quoteTask != null) {
			synchronized (this.quoteTask) {
				this.quoteTask.notifyAll();
			}
		}
	}

	public OrdersView(DefaultController controller) {
		this.controller = controller;
	}

	private void init() {
		this.screen = new OandaMainScreen() {
			protected void onUiEngineAttached(boolean attached) {
				if (attached) {
					Logger.log("Orders View onUiEngineAttached true");
					showThrobberPlain();
					OrdersView.this.controller
							.orderList(null, null, null, null);
				} else {
					Logger.log("Orders View onUiEngineAttached false");
					OrdersView.this.stopOrderPollThread();
					OrdersView.this.stopQuoteUpdateThread();
					OrdersView.this.listManager.deleteAll();
					OrdersView.this.list = null;
				}
			}

			protected void makeMenu(Menu menu, int instance) {
				menu.add(OrdersView.this.newOrder);
				if (OrdersView.this.list != null) {
					menu.add(OrdersView.this.viewDetails);
					menu.add(OrdersView.this.cancelOrder);
				}
				menu.add(OrdersView.this.back);
			}
		};
		this.screen.getMainManager().setBackground(
				BackgroundFactory.createSolidBackground(4473924));
		this.screen.updateTitle("Orders");

		this.screen.add(this.listManager);
	}

	private void setOrders(final OrderListResponse[] orders) {
		if (this.screen != null) {
			this.screen.hideThrobber();
		}

		if (orders == null) {
			DefaultController.inform("no orders entries");
		}

		final OrdersView callback = this;
		UiApplication.getUiApplication().invokeLater(new Runnable() {
			private final OrderListResponse[] _orders = orders;
			private final OrdersView _callback = callback;

			public void run() {
				if ((OrdersView.this.list == null) && (this._orders != null)
						&& (this._orders.length > 0)) {
					OrderListResponse.sort(this._orders);
					OrdersView.this.list = new OrdersListField(this._orders);
					OrdersView.this.list.setCallback(this._callback);
					OrdersView.this.listManager.add(OrdersView.this.list
							.getList());
				} else {
					OrdersView.this.list.update(this._orders);
				}
			}
		});
	}

	private void startOrderPollThread() {
		if (this.updateTimer == null) {
			this.updateTimer = new Timer();
		}
		if (this.updateTask == null)
			this.updateTask = new TimerTask() {
				public void run() {
					OrdersView.this.orderPoll();
				}
			};
		try {
			this.updateTimer.schedule(this.updateTask, 1000L, this.UPDATE_TIME);
		} catch (IllegalStateException e) {
		}
	}

	private void startQuoteUpdateThread() {
		if (this.quoteTimer == null) {
			this.quoteTimer = new Timer();
		}

		if (this.quoteTask == null)
			this.quoteTask = new TimerTask() {
				public void run() {
					OrdersView.this.quoteUpdates();
				}
			};
		try {
			this.quoteTimer.schedule(this.quoteTask, 1000L,
					this.UPDATE_TIME_QUOTE);
		} catch (IllegalStateException e) {
		}
	}

	private void stopOrderPollThread() {
		Logger.log("orders view stopOrderPoll on UI EngineAttached cancelling");
		if (this.updateTask != null) {
			this.updateTask.cancel();
			this.updateTask = null;
		}

		if (this.updateTimer != null) {
			Logger.log("cancelling");
			this.updateTimer.cancel();
			this.updateTimer = null;
			Logger.log("Canceled");
		}
	}

	private void stopQuoteUpdateThread() {
		Logger.log("orders view quoteUpdateThread on UI EngineAttached cancelling");
		if (this.quoteTask != null) {
			this.quoteTask.cancel();
			this.quoteTask = null;
		}
		if (this.quoteTimer != null) {
			Logger.log("cancelling");
			this.quoteTimer.cancel();
			this.quoteTimer = null;
		}
		Logger.log("Canceled");
	}

	private void orderPoll() {
		if ((this.screen != null)
				&& (UiApplication.getUiApplication().getActiveScreen()
						.equals(this.screen))) {
			this.controller.orderPoll();
			this.controller.turnOnBacklight();
		}
	}

	private void quoteUpdates() {
		if ((this.screen != null)
				&& (UiApplication.getUiApplication().getActiveScreen()
						.equals(this.screen))) {
			String s = getListSymbols();
			if ((s != null) && (s.length() > 0))
				this.controller.quote(Model.getModel().getSessionToken(), s,
						null);
		}
	}

	public void modelPropertyChange(PropertyChangeEvent evt) {
		if (evt.getPropertyName().equals("OrderListException")) {
			if (this.list == null) {
				String message = "error occured";
				if ((evt.getNewValue() != null)
						&& ((evt.getNewValue() instanceof String))) {
					message = (String) evt.getNewValue();
				}

				if (this.screen != null) {
					this.screen.diplayError(message, 3000);
				}
				final String fMessage = message;
				Runnable r = new Runnable() {
					private final String _fMessage=fMessage;

					public void run() {
						String askText = "Retry?";
						if ((this._fMessage != null)
								&& (this._fMessage.length() > 0)) {
							askText = askText + "(" + this._fMessage + ")";
						}
						int i = Dialog.ask(3, askText, 4);
						if (i == 4)
							OrdersView.this.controller.orderList(null, null,
									null, null);
						else if (i == -1) {
							OrdersView.this.popScreen();
						}
					}
				};
				this.controller.invokeLater(r);
			}

		} else if (evt.getPropertyName().equals("setOrderListError")) {
			if (this.screen != null)
				this.screen.diplayError((String) evt.getNewValue(), 2500);
		} else if (evt.getPropertyName().equals("setRateQuote")) {
			if ((evt.getNewValue() != null)
					&& ((evt.getNewValue() instanceof Rate))) {
				Rate rate = (Rate) evt.getNewValue();
				if (this.list != null)
					this.list.setQuotes(rate.getQuotes());
			}
		} else if (evt.getPropertyName().equals("setOrderPollResponse")) {
			if ((evt.getNewValue() != null)
					&& ((evt.getNewValue() instanceof OrderPollResponse))) {
				OrderPollResponse response = (OrderPollResponse) evt
						.getNewValue();
				updateList(response);
			}
		} else if (evt.getPropertyName().equals("removeOrderListStatus")) {
			if (this.screen != null)
				this.screen.removeStatusField();
		} else if (evt.getPropertyName().equals("setOrderListStatus")) {
			if (this.screen != null)
				this.screen.setStatusField((String) evt.getNewValue());
		} else if (evt.getPropertyName().equals("setOrderList")) {
			Logger.log("z1");
			if ((evt.getNewValue() != null)
					&& ((evt.getNewValue() instanceof OrderListResponse[]))) {
				Logger.log("z11");
				setOrders((OrderListResponse[]) (OrderListResponse[]) evt
						.getNewValue());
			} else {
				Logger.log("z12");
				if ((this.screen != null)
						&& (UiApplication.getUiApplication().getActiveScreen()
								.equals(this.screen))) {
					StatusView2.showInfoDialog("No Open Orders.",
							new OKDialogListener() {
								public void performAction(Object o) {
									StatusView2
											.showYesNoDialog(
													"Do you want to create a new order now?",
													new OKDialogListener() {
														public void performAction(
																Object o) {
															if (((Boolean) o)
																	.booleanValue()) {
																OrdersView.this.controller
																		.propertyChange(new PropertyChangeEvent(
																				this,
																				"newLimitOrderOpenBuy",
																				null,
																				null));
															} else
																OrdersView.this
																		.popScreen();
														}
													});
								}
							}, false);
				}

			}

			startOrderPollThread();
			startQuoteUpdateThread();
		} else if (evt.getPropertyName().equals("showOrdersView")) {
			init();
			if (this.screen != null)
				this.controller.pushScreen(this.screen);
		} else if ((evt.getPropertyName().equals("orderClosed"))
				&& (evt.getNewValue() != null)
				&& ((evt.getNewValue() instanceof String))) {
			if (this.list != null)
				try {
					long l = Long.parseLong((String) evt.getNewValue());
					long[] deleted = new long[1];
					deleted[0] = l;
					Logger.log("start removing");
					this.list.remove(deleted);
				} catch (NumberFormatException ne) {
					Logger.log("Unable to pasre orderClosed value.");
				}
		}
	}

	public void popScreen() {
		if (this.screen != null) {
			this.controller.popScreen(this.screen);
			this.screen.onClose();
		}
		this.screen = null;
	}

	private void updateList(OrderPollResponse response) {
		Logger.log("Order view updateList");
		if (response != null) {
			if ((response.getDeleted() != null)
					&& (response.getDeleted().length > 0)) {
				if ((this.list != null) && (response != null)) {
					this.list.remove(response.getDeleted());
				}
			}

			if ((response.getCreated() != null)
					&& (response.getCreated().length > 0)) {
				String maxOpenedId = Long.toString(response.getMaxOpenedId());
				long l = response.getMaxOrderId() - Order.getMaxOrderId();
				String maxCount = Long.toString(l);
				this.controller.orderList(maxOpenedId, maxCount, null, null);
			}

			if ((response.getUpdated() != null)
					&& (response.getUpdated().length > 0)) {
				String maxCount = String.valueOf(response.getUpdated().length);
				this.controller.orderList(null, maxCount, null,
						response.getAllUpdatedIds());
			}

			if (response.getMaxOrderId() > Order.getMaxOrderId()) {
				String maxOpenedId = Long.toString(response.getMaxOpenedId());
				long l = response.getMaxOrderId() - Order.getMaxOrderId();
				String maxCount = Long.toString(l);
				this.controller.orderList(maxOpenedId, maxCount, null, null);
			}
		}
	}

	private String getListSymbols() {
		StringBuffer buffer = new StringBuffer();

		if (this.list == null)
			return null;

		OrderListResponse[] data = this.list.getOrderListResponses();
		for (int i = 0; (data != null) && (i < data.length); i++) {
			if (data[i] == null) {
				Logger.log("data[" + String.valueOf(i) + "]");
			} else {
				String object = data[i].getSymbol();
				buffer.append(object);
				buffer.append(',');
			}
		}

		if (buffer.length() > 1) {
			buffer = buffer.deleteCharAt(buffer.length() - 1);
		}
		return buffer.toString();
	}
}
